from sanic import exceptions
from sanic import response
from utils.FileUtils import download_file
from utils.ImageChecker import check_image
from service.ImageClassfyService import *
from config.ServerApp import app, async_execute, api_model_pool
from utils.DataUtil import *
from service.OcrHandlerService import ocr_extract
from service.ImageClassfyService import get_ocr_only_result, batch_images_ocr_commit


def __single_validate_params(params: dict):
    """
    参数校验
    :param params: 
    :return: img_path
    """
    if not params:
        raise exceptions.NotFound("图片分类参数不得为空！")
    if "imageUrl" not in params:
        raise exceptions.NotFound("图片分类参数imageUrl不得为空！")
    if "uniqueId" not in params:
        raise exceptions.NotFound("图片分类参数uniqueId不得为空！")
    # 图片地址以及验证对应图片地址是否存在，以及下载下来图片是否损坏或为正常图片
    image_url = params['imageUrl']
    ext_params = {}
    file_system_type = params.get("fileSystemType", "")
    ftp_config_encrypt = params["ftpConfigEncrypt"] if "ftpConfigEncrypt" in params else ''
    if file_system_type == 'ftp':
        ext_params = json.loads(EncryptUtil.decrypt_aes(encrypt_key, ftp_config_encrypt))
    img_path = download_file(image_url, file_system_type, ext_params)
    if img_path is None:
        raise exceptions.SanicException("提供的图片地址无效下载失败！")
    is_valid, message = check_image(img_path)
    if not is_valid:
        raise exceptions.SanicException(message)
    return img_path


@app.route("/single/image/ocr/extract", methods=['POST'])
async def singleImageOcrExtract(request):
    """
    单图片OCR提取接口（仅返回文本，不做分类）

    请求示例：
    {
        "imageUrl": "http://host/path/to/image.png",
        "fileSystemType": "ftp", // 可选：ftp/uri
        "ftpConfigEncrypt": "aes加密后的ftp配置", // 当 fileSystemType=ftp 时需要
        "uniqueId": "xxxx"
    }
    """
    local_img_path = None
    try:
        params = request.json
        app.ctx.logger.info(f"************【single image ocr extract START】{params}************")
        local_img_path = await async_execute(request, lambda: __single_validate_params(params))
        ocr_text = await async_execute(request, lambda: ocr_extract(local_img_path), pool=api_model_pool)
        return response.json({
            "extInfo": "",
            "msg": "",
            "code": 200,
            "data": {
                "imageUrl": params.get('imageUrl', ''),
                "uniqueId": params.get('uniqueId', ''),
                "ocrText": ocr_text
            }
        })
    except Exception as e:
        if local_img_path:
            remove_img(local_img_path)
        app.ctx.logger.error(str(e), exc_info=True)
        return response.json(build_fail_result(e, None), status=500)


@app.route("/single/image/classify", methods=['POST'])
async def singleImageClassify(request):
    """
    单图片-分类-处理接口

    {
    "imageUrl": "http://10.118.21.239:91//dev/20221205/ANNEX/137-589874455-111111-111111-1670226912-00011/th_ebbd4de9229f83e067e685a6142673a3",
    // "imageUrl":"http://10.118.21.239:91//dev/20250401/ANNEX/137-705420347-330205-330205-1743504577-00001/at
    "fileSystemType":"ftp", // 非必填  ftp:ftp服务 , uri:url/path
        "apiConfig" : {
        //aes加密 java可引用 hutool aes加密工具t/bb.txt",
    "uniqueId": 1732981489,
            "ftpConfigEncrypt":"aes加密ftp配置 "
        }
    }
    """
    local_img_path = None
    try:
        params = request.json
        app.ctx.logger.info(f"************【single image  classfy  START】{params}************")
        local_img_path = await async_execute(request, lambda: __single_validate_params(params))
        response_result = await async_execute(request, lambda: image_classify_route(local_img_path, params['imageUrl'],
                                                                                    params['uniqueId'],
                                                                                    params), pool=api_model_pool)
        return response.json(response_result)
    except Exception as e:
        if local_img_path:
            remove_img(local_img_path)
        app.ctx.logger.error(str(e), exc_info=True)
        return response.json(build_fail_result(e, None), status=500)


def __batch_validate_params(params: dict):
    """
    参数校验
    :param params: 
    """
    if not params:
        raise exceptions.NotFound("批量处理图片参数不得为空！")
    if "batchId" not in params:
        raise exceptions.NotFound("批次batchId不得为空！")
    if "imageList" not in params:
        raise exceptions.NotFound("待处理图片列表imageList不得为空！")
    img_list = params['imageList']
    if img_list is None or len(img_list) == 0:
        raise exceptions.NotFound("待处理图片列表imageList不得为空！")
    pass


@app.route("/batch/image/commit/classify", methods=['POST'])
async def batchImageOrcExtract(request):
    """
    批量图片处理


    {
    "batchId": "批次号",
    "fileSystemType":"ftp", // 非必填  ftp:ftp服务 , uri:url/path
    //aes加密 java可引用 hutool aes加密工具
    "ftpConfigEncrypt":"aes加密ftp配置 ",
    "imageList": [
        {
            "imageUrl": "/test/20250307/test1/shopping/", // ftp 目录末尾需要/
            "uniqueId": "{{$randomUUID}}"
        },
        {
            "imageUrl": "http://10.118.21.135:8091/5503769682/总料/新建文件夹 (3)/00001.png", //uri
            "uniqueId": "dd780640-1a4d-43e7-82f2-223f2fdbab62"
        },
        {
            "imageUrl": "/test/20250307/0BQ0FJ7YPA66.jpg", // ftp 单文件
            "uniqueId": "{{$randomUUID}}"
        },
    ]
}
    """
    try:
        params = request.json
        app.ctx.logger.info(f"************【batch images  classfy  START】{params}************")
        __batch_validate_params(params)
        return await async_execute(request, lambda: batch_images_classfy(params))
    except Exception as e:
        app.ctx.logger.error(e)
        return response.json(build_fail_result(e, None), status=500)


 


@app.route("/batch/image/ocr/extract", methods=['POST'])
async def batchImageOcrCommit(request):
    """
    批量图片OCR提交（异步提交，使用 /batch/image/ocr/query/<batchId> 查询结果）
    请求体与同步提取一致
    """
    try:
        params = request.json
        app.ctx.logger.info(f"************【batch images ocr commit START】{params}************")
        __batch_validate_params(params)
        return await async_execute(request, lambda: batch_images_ocr_commit(params))
    except Exception as e:
        app.ctx.logger.error(str(e), exc_info=True)
        return response.json(build_fail_result(e, None), status=500)


@app.route("/batch/image/query/classify/<batchId>", methods=['GET'])
async def getImageClassifyResult(request, batchId: str):
    """
    获取批量图片处理结果
    """
    try:
        app.ctx.logger.info(f"************【query batch result START】：{batchId}！************")
        return await async_execute(request, lambda: get_img_classfy_result(batchId))
    except Exception as e:
        app.ctx.logger.error(e)
        return response.json({
            "extInfo": str(e),
            "code": 500,
            "data": None,
            "msg": f"接口执行异常:{str(e)}"
        }, status=500)



@app.route("/batch/image/ocr/query/<batchId>", methods=['GET'])
async def getImageOcrBatchResult(request, batchId: str):
    """
    获取批量图片OCR文本结果（异步查询），仅返回OCR文本
    """
    try:
        app.ctx.logger.info(f"************【query batch ocr result START】：{batchId}！************")
        return await async_execute(request, lambda: get_ocr_only_result(batchId))
    except Exception as e:
        app.ctx.logger.error(e)
        return response.json({
            "extInfo": str(e),
            "code": 500,
            "data": None,
            "msg": f"接口执行异常:{str(e)}"
        }, status=500)
